package com.icloud.auth.boot.config.auth;

import com.alibaba.fastjson.JSONObject;
import com.nimbusds.jose.JWSObject;
import com.icloud.auth.boot.service.impl.UserServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.text.ParseException;
import java.util.LinkedHashMap;
import java.util.Map;

public class ScanTokenGranter extends AbstractTokenGranter {

    private static final String GRANT_TYPE = "scan";

    private final UserServiceImpl userService;

    public ScanTokenGranter(AuthorizationServerTokenServices tokenServices,
                            ClientDetailsService clientDetailsService,
                            OAuth2RequestFactory requestFactory,
                            UserServiceImpl userService) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.userService = userService;
    }


    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client,
                                                           TokenRequest tokenRequest) {

        Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());

        // 客户端提交的扫码用户token
        String scanAccessToken = parameters.get("scan_access_token");
        if (StringUtils.isBlank(scanAccessToken)) {
            throw new InvalidGrantException("scan access token is null ！");
        }
        //校验scanAccessToken是否正确
        String userName;
        try {
            JWSObject jwsObject = JWSObject.parse(scanAccessToken);
            String userStr = jwsObject.getPayload().toString();
            JSONObject userJson = JSONObject.parseObject(userStr);
            if (userJson == null || userJson.getString("user_name") == null) {
                throw new InvalidGrantException("scan access token parse error ！");
            }
            userName = userJson.getString("user_name");
        } catch (ParseException e) {
            throw new InvalidGrantException("scan access token parse error ！");
        }

        UserDetails user = userService.loadUserByUsername(userName);

        AbstractAuthenticationToken userAuth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());

        userAuth.setDetails(parameters);
        OAuth2Request oAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        return new OAuth2Authentication(oAuth2Request, userAuth);
    }
}
